package com.xu.cloud.auth.component.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xu.cloud.auth.component.UserInfoComponent;
import com.xu.cloud.auth.exception.AuthErrorCodeEnum;
import com.xu.cloud.auth.pojo.domain.*;
import com.xu.cloud.auth.pojo.mapper.*;
import com.xu.cloud.common.auth.AuthContext;
import com.xu.cloud.common.util.AssertUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户信息组件实现类
 *
 * @author xuguan
 * @since 2025/2/23
 */
@Slf4j
@Component
public class UserInfoComponentImpl implements UserInfoComponent {

    @Autowired
    private UserInfoMapper userInfoMapper;
    @Autowired
    private RoleInfoMapper roleInfoMapper;
    @Autowired
    private PermissionInfoMapper permissionInfoMapper;
    @Autowired
    private UserRoleInfoMapper userRoleInfoMapper;
    @Autowired
    private RolePermissionMapper rolePermissionMapper;

    @Nullable
    @Override
    public UserInfoDO queryUserInfoByUserId(Long userId) {
        log.info("通过用户id查询用户信息开始, userId={}", userId);
        AssertUtil.assertNotNull(userId);
        final UserInfoDO userInfoDo = userInfoMapper.selectById(userId);
        log.info("通过用户id查询用户信息结束, userInfoDo={}", userInfoDo);
        return userInfoDo;
    }

    @Override
    public UserInfoDO queryUserInfoByMobileNo(String mobileNo) {
        log.info("通过手机号查询用户信息开始, mobileNo={}", mobileNo);
        AssertUtil.assertNotNull(mobileNo);
        final UserInfoDO userInfoDo = userInfoMapper.selectOne(Wrappers.lambdaQuery(UserInfoDO.class)
                .eq(UserInfoDO::getMobileNo, mobileNo));
        log.info("通过用户id查询用户信息结束, userInfoDo={}", userInfoDo);
        return userInfoDo;
    }

    @Nullable
    @Override
    public UserInfoDO queryUserInfoByLoginName(String loginName) {
        log.info("通过登录名查询用户信息开始, loginName={}", loginName);
        AssertUtil.assertHasText(loginName);

        final LambdaQueryWrapper<UserInfoDO> userInfoQw = Wrappers.lambdaQuery(UserInfoDO.class);
        userInfoQw.eq(UserInfoDO::getMobileNo, loginName);
        UserInfoDO userInfoDo;
        userInfoDo = userInfoMapper.selectOne(userInfoQw);
        if (Objects.nonNull(userInfoDo)) {
            log.info("查询用户信息成功, 登录名为手机号, userInfoDo={}", userInfoDo);
            return userInfoDo;
        }
        userInfoQw.clear();
        userInfoQw.eq(UserInfoDO::getEmail, loginName);
        userInfoDo = userInfoMapper.selectOne(userInfoQw);
        if (Objects.nonNull(userInfoDo)) {
            log.info("查询用户信息成功, 登录名为邮箱, userInfoDo={}", userInfoDo);
            return userInfoDo;
        }
        userInfoQw.clear();
        userInfoQw.eq(UserInfoDO::getUsername, loginName);
        userInfoDo = userInfoMapper.selectOne(userInfoQw);
        if (Objects.nonNull(userInfoDo)) {
            log.info("查询用户信息成功, 登录名为用户名, userInfoDo={}", userInfoDo);
            return userInfoDo;
        }

        log.info("通过登录名未查询到用户信息");
        return null;
    }

    @Override
    public AuthContext queryAuthContext(Long userId) {
        log.info("通过用户id查询用户角色权限信息开始, userId={}", userId);
        AssertUtil.assertNotNull(userId);

        final UserInfoDO userInfoDo = userInfoMapper.selectById(userId);
        AssertUtil.assertNotNull(userInfoDo, AuthErrorCodeEnum.USER_INFO_NOT_EXIST.info().newException());

        final AuthContext authContext = new AuthContext();
        authContext.setUserId(userId);

        final List<UserRoleDO> userRoleDos = userRoleInfoMapper.selectList(Wrappers.lambdaQuery(UserRoleDO.class).eq(UserRoleDO::getUserId, userId))
                .stream().distinct().collect(Collectors.toList());
        if (CollectionUtils.isEmpty(userRoleDos)) {
            authContext.setRoles(Collections.emptyList());
            authContext.setPermissions(Collections.emptyList());
            log.info("查询用户角色权限信息结束, authContext={}", authContext);
            return authContext;
        }

        final List<Long> roleIds = userRoleDos.stream().map(UserRoleDO::getRoleId).collect(Collectors.toList());
        final List<RoleInfoDO> roleInfoDos = roleInfoMapper.selectBatchIds(roleIds)
                .stream().distinct().collect(Collectors.toList());
        final Set<String> roleNames = roleInfoDos.stream().map(RoleInfoDO::getRoleName).collect(Collectors.toSet());
        authContext.setRoles(new ArrayList<>(roleNames));
        for (Long roleId : roleIds) {
            final List<RolePermissionDO> rolePermissionDos = rolePermissionMapper.selectList(Wrappers.lambdaQuery(RolePermissionDO.class).eq(RolePermissionDO::getRoleId, roleId))
                    .stream().distinct().collect(Collectors.toList());
            final Set<Long> permissionIds = rolePermissionDos.stream().map(RolePermissionDO::getPermissionId).collect(Collectors.toSet());
            final List<PermissionInfoDO> permissionInfoDos = permissionInfoMapper.selectBatchIds(permissionIds)
                    .stream().distinct().collect(Collectors.toList());
            final Set<String> permissionNames = permissionInfoDos.stream().map(PermissionInfoDO::getPermissionName).collect(Collectors.toSet());
            authContext.setPermissions(new ArrayList<>(permissionNames));
        }

        log.info("查询用户角色权限信息结束, authContext={}", authContext);
        return authContext;
    }
}
